/**
 * org.assess.core.common.SecurityUtils
 */
package org.assess.core.common;

import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;

import org.apache.log4j.Logger;

/**
 * @description 加解密工具
 * @author XiaLongxiang
 * @createtime 2012-2-12 上午1:02:07
 */
public final class SecurityUtils {
    /** 日志对象 */
    private static Logger logger = Logger.getLogger(SecurityUtils.class);
    
    /**
     * RSA加密
     * @param value 需要加密的数据
     * @param encode 加密密钥
     * @return 返回null说明加密失败
     */
    public static byte[] encryptRSA(byte[] value, byte[] encode) {
        byte[] result = null;
        try {
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            X509EncodedKeySpec keyspec = new X509EncodedKeySpec(encode);
            PublicKey key = keyFactory.generatePublic(keyspec);
            
            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            cipher.init(Cipher.ENCRYPT_MODE, key);
            result = cipher.doFinal(value);
        }
        catch (Exception ex) {
            logger.error(ex);
        }
        
        return result;
    }
    
    /**
     * RSA解密
     * @param value 需要解密的数据
     * @param encode 解密密钥
     * @return 返回null说明解密失败
     */
    public static byte[] decryptRSA(byte[] value, byte[] encode) {
        byte[] result = null;
        try {
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PKCS8EncodedKeySpec keyspec = new PKCS8EncodedKeySpec(encode);
            PrivateKey key = keyFactory.generatePrivate(keyspec);
            
            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            cipher.init(Cipher.DECRYPT_MODE, key);
            result = cipher.doFinal(value);
        }
        catch (Exception ex) {
            logger.error(ex);
        }
        
        return result;
    }
    
    /**
     * DES加密
     * @param value 需要加密的byte数组
     * @return encode 加密密钥
     * @return 返回null说明加密失败
     */
    public final static byte[] encryptDES(byte[] value, byte[] encode) {
        byte[] result = null;
        try {
            DESKeySpec keyspec = new DESKeySpec(encode);
            SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("DES");
            SecretKey secretKey = secretKeyFactory.generateSecret(keyspec);
            Cipher cipher = Cipher.getInstance("DES");
            cipher.init(Cipher.ENCRYPT_MODE, secretKey);
            result = cipher.doFinal(value);
        }
        catch (Exception e) {
            logger.error(e);
        }
        return result;
        
    }
    
    /**
     * DES解密
     * @param value 需要解密的byte数组
     * @param encode 解密密钥
     * @return 返回null说明解密失败
     */
    public final static byte[] decryptDES(byte[] value, byte[] encode) {
        byte[] result = null;
        try {
            DESKeySpec keyspec = new DESKeySpec(encode);
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
            SecretKey secretKey = keyFactory.generateSecret(keyspec);
            Cipher cipher = Cipher.getInstance("DES");
            cipher.init(Cipher.DECRYPT_MODE, secretKey);
            result = cipher.doFinal(value);
        }
        catch (Exception e) {
            logger.error(e);
        }
        return result;
    }
    
    /**
     * 加密 MD5
     * @param value 需要加密的数据
     * @return 返回null说明加密失败
     */
    public final static byte[] encryptMD5(byte[] value) {
        byte[] result = null;
        try {
            MessageDigest messageDigest = MessageDigest.getInstance("MD5");
            messageDigest.reset();
            result = messageDigest.digest(value);
        }
        catch (Exception ex) {
            logger.error(ex);
        }
        return result;
    }
    
    /**
     * 加密MD5
     * @param value
     * @return
     */
    public final static String encryptMD5(String value) {
        byte[] _bp = encryptMD5(value.getBytes());
        return StringUtils.parse16(_bp, false);
    }
    
    public final static byte[] encryptSHA256(byte[] value) {
        byte[] result = null;
        try {
            MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
            messageDigest.reset();
            result = messageDigest.digest(value);
        }
        catch (Exception ex) {
            logger.error(ex);
        }
        return result;
    }
    
    /**
     * 获取RSA的KeyPair，其中包含了一对公钥/密钥
     * @return
     * @throws Exception
     */
    public static KeyPair getKeyPair(int length) {
        try {
            KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
            keyGen.initialize(length);
            return keyGen.generateKeyPair();
        }
        catch (NoSuchAlgorithmException e) {
            return null;
        }
    }
    
    public static void testRSA() throws Exception {
        byte[] value = "cefa".getBytes();
        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
        keyGen.initialize(1024);
        KeyPair keyPair = keyGen.generateKeyPair();
        
        byte[] eb1 = encryptRSA(value, keyPair.getPublic().getEncoded());
        byte[] db1 = decryptRSA(eb1, keyPair.getPrivate().getEncoded());
        System.out.println(new String(eb1));
        System.out.println(new String(db1));
    }
    
    public static void testDES() throws Exception {
        byte[] value = "nihao哈哈&*&".getBytes();
        byte[] encryptValue = encryptDES(value, "faf2!r&&743".getBytes());
        byte[] decryptValue = decryptDES(encryptValue, "faf2!r&&743".getBytes());
        System.out.println(new String(decryptValue));
    }
    
    public static void testMD5() {
        byte[] value = "nihao哈哈&*&".getBytes();
        byte[] eb1 = encryptMD5(value);
        System.out.println(new String(eb1));
    }
    
    public static void main(String[] args) {
        System.out.println(SecurityUtils.encryptMD5("111111aa"));
    }
}
